package com.hulk.ratel.config;


import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.extension.MybatisMapWrapperFactory;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.extension.plugins.SqlExplainInterceptor;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
import com.hulk.ratel.config.tenant.RatelTenantHandler;
import com.hulk.ratel.persistence.handler.CommonMetaObjectHandler;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import java.util.ArrayList;
import java.util.List;


/**
 * @author cmt
 *
 */
@Configuration
public class MybatisPlusConfig {


//	@Bean("mybatisSqlSession")
//	public SqlSessionFactory sqlSessionFactory(DataSource dataSource, GlobalConfig globalConfig,
//											   PaginationInterceptor paginationInterceptor) throws Exception {
//		MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
//		/* 数据源 */
//		sqlSessionFactory.setDataSource(dataSource);
//		/* 枚举扫描 */
//		sqlSessionFactory.setTypeEnumsPackage("com.baomidou.mybatisplus.test.base.enums");
//		/* xml扫描 */
//		sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
//				.getResources("classpath:/mapper/*.xml"));
//		/* 扫描 typeHandler */
////        sqlSessionFactory.setTypeHandlersPackage("com.baomidou.mybatisplus.test.base.type");
//		MybatisConfiguration configuration = new MybatisConfiguration();
//		configuration.setJdbcTypeForNull(JdbcType.NULL);
//		/* 驼峰转下划线 */
//		configuration.setMapUnderscoreToCamelCase(true);
//		/* 分页插件 */
//		configuration.addInterceptor(paginationInterceptor);
//		/* 乐观锁插件 */
//		configuration.addInterceptor(new OptimisticLockerInterceptor());
//		/* map 下划线转驼峰 */
//		configuration.setObjectWrapperFactory(new MybatisMapWrapperFactory());
//		sqlSessionFactory.setConfiguration(configuration);
//		/* 自动填充插件 */
//		globalConfig.setMetaObjectHandler(new CommonMetaObjectHandler());
//		sqlSessionFactory.setGlobalConfig(globalConfig);
//		return sqlSessionFactory.getObject();
//	}
//
//	@Bean
//	public GlobalConfig globalConfig() {
//		GlobalConfig conf = new GlobalConfig();
//		conf.setDbConfig(new GlobalConfig.DbConfig()
//				.setColumnFormat("`%s`"));
//		DefaultSqlInjector logicSqlInjector = new DefaultSqlInjector() {
//			/**
//			 * 注入自定义全局方法
//			 */
//			@Override
//			public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
//				List<AbstractMethod> methodList = super.getMethodList(mapperClass);
//				methodList.add(new LogicDeleteByIdWithFill());
//				// 不要逻辑删除字段, 不要乐观锁字段, 不要填充策略是 UPDATE 的字段
//				methodList.add(new InsertBatchSomeColumn(t -> !t.isLogicDelete() && !t.isVersion() && t.getFieldFill() != FieldFill.UPDATE));
//				// 不要填充策略是 INSERT 的字段, 不要字段名是 column4 的字段
//				methodList.add(new AlwaysUpdateSomeColumnById(t -> t.getFieldFill() != FieldFill.INSERT && !t.getProperty().equals("column4")));
//				return methodList;
//			}
//		};
//		conf.setSqlInjector(logicSqlInjector);
//		return conf;
//	}


	@Bean
	public MapperScannerConfigurer mapperScannerConfigurer() {
		MapperScannerConfigurer scannerConfigurer = new MapperScannerConfigurer();
		scannerConfigurer.setBasePackage("com.hulk.ratel.persistence.mapper*");
		return scannerConfigurer;
	}


	/**
	 * 创建租户维护处理器对象
	 *
	 * @return 处理后的租户维护处理器
	 */
	@Bean
	@ConditionalOnMissingBean
	public RatelTenantHandler ratelTenantHandler() {
		return new RatelTenantHandler();
	}

	/**
	 * 分页插件
	 *
	 * @param tenantHandler 租户处理器 具体方法上使用@com.baomidou.mybatisplus.annotation.SqlParser 注解
	 * @return PaginationInterceptor
	 */
	@Bean
	@ConditionalOnMissingBean
	public PaginationInterceptor paginationInterceptor(RatelTenantHandler tenantHandler) {
		PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
		List<ISqlParser> sqlParserList = new ArrayList<>();
		TenantSqlParser tenantSqlParser = new TenantSqlParser();
		tenantSqlParser.setTenantHandler(tenantHandler);
		sqlParserList.add(tenantSqlParser);
		paginationInterceptor.setSqlParserList(sqlParserList);
		return paginationInterceptor;
	}

	/*
	 * 逻辑删除
	 */
	@Bean
	@ConditionalOnMissingBean
	public ISqlInjector sqlInjector() {
		DefaultSqlInjector logicSqlInjector = new DefaultSqlInjector();
		/*{
			@Override //注入自定义全局方法
			public List<AbstractMethod> getMethodList() {
				List<AbstractMethod> methodList = super.getMethodList();
				methodList.add(new LogicDeleteByIdWithFill());
				// 不要逻辑删除字段, 不要乐观锁字段, 不要填充策略是 UPDATE 的字段
				methodList.add(new InsertBatchSomeColumn(t -> !t.isLogicDelete() && !t.isVersion() && t.getFieldFill() != FieldFill.UPDATE));
				// 不要填充策略是 INSERT 的字段, 不要字段名是 column4 的字段
				methodList.add(new AlwaysUpdateSomeColumnById(t -> t.getFieldFill() != FieldFill.INSERT && !t.getProperty().equals("column4")));
				return methodList;
			}
		};*/
		return logicSqlInjector;
	}

	/**
	 * mybatis-plus乐观锁插件
	 * 
	 */
	@Bean
	public OptimisticLockerInterceptor optimisticLockerInterceptor() {
		OptimisticLockerInterceptor lock = new OptimisticLockerInterceptor();
		return lock;
	}

	/**
	 * 自动填充
	 *
	 * @return
	 */
	//@Bean
	public CommonMetaObjectHandler commonMetaObjectHandler() {
		return new CommonMetaObjectHandler();
	}




	/**
	 * SQL执行效率插件
	 */
	@Bean
	@Profile({"dev","test"})// 设置 dev test 环境开启
	public PerformanceInterceptor performanceInterceptor() {
		PerformanceInterceptor page = new PerformanceInterceptor();
		page.setMaxTime(60000);
		page.setFormat(true);
		return page;
	}


	//SQL 执行分析拦截器【 目前只支持 MYSQL-5.6.3 以上版本 】，作用是分析 处理 DELETE UPDATE 语句， 防止小白或者恶意 delete update 全表操作！
	@Bean
    @Profile({"dev","test"})// 设置 dev test 环境开启
	public SqlExplainInterceptor sqlExplainInterceptor() {
		SqlExplainInterceptor sql = new SqlExplainInterceptor();
		return sql;
	}

	/* map 下划线转驼峰 */
	@Bean
	public	MybatisMapWrapperFactory   mybatisMapWrapperFactory(){
		return  new MybatisMapWrapperFactory();
	}




	/**
	 * 自定义注入语句
	 *
	 * @return
	 */
//	@Bean
//	public MybatisPlusSqlInjector mybatisPlusSqlInjector() {
//		return new MybatisPlusSqlInjector();
//	}

}
